;; -------- awesome-tab --------
(use-package awesome-tab
  :load-path "lazycat-bucket/awesome-tab"
  :hook
  ((after-init) . awesome-tab-mode)
  :config
  (setq awesome-tab-ace-quit-keys '(?\C-g))
  ;; winum users can use `winum-select-window-by-number' directly.
  (defun my-select-window-by-number (win-id)
    "Use `ace-window' to select the window by using window index.
WIN-ID : Window index."
    (let ((wnd (nth (- win-id 1) (aw-window-list))))
      (if wnd
          (aw-switch-to-window wnd)
        (message "No such window."))))
  (defun my-select-window ()
    (interactive)
    (let* ((event last-input-event)
           (key (make-vector 1 event))
           (key-desc (key-description key)))
      (my-select-window-by-number
       (string-to-number (car (nreverse (split-string key-desc "-")))))))
  (defhydra awesome-fast-switch (global-map "C-<tab>" :hint nil)
    "
 ^^^^Fast Move             ^^^^Tab                    ^^Search            ^^Misc
-^^^^--------------------+-^^^^---------------------+-^^----------------+-^^---------------------------
   ^_k_^   prev group    | _C-a_^^     select first | _b_ search buffer | _C-k_   kill buffer
 _h_   _l_  switch tab   | _C-e_^^     select last  | _g_ search group  | _C-S-k_ kill others in group
   ^_j_^   next group    | _C-j_^^     ace jump     | ^^                | ^^
 ^^0 ~ 9^^ select window | _C-h_/_C-l_ move current | ^^                | ^^
-^^^^--------------------+-^^^^---------------------+-^^----------------+-^^---------------------------
"
    ("h" awesome-tab-backward-tab)
    ("j" awesome-tab-forward-group)
    ("k" awesome-tab-backward-group)
    ("l" awesome-tab-forward-tab)
    ("0" my-select-window)
    ("1" my-select-window)
    ("2" my-select-window)
    ("3" my-select-window)
    ("4" my-select-window)
    ("5" my-select-window)
    ("6" my-select-window)
    ("7" my-select-window)
    ("8" my-select-window)
    ("9" my-select-window)
    ("C-a" awesome-tab-select-beg-tab)
    ("C-e" awesome-tab-select-end-tab)
    ("C-j" awesome-tab-ace-jump)
    ("C-h" awesome-tab-move-current-tab-to-left)
    ("C-l" awesome-tab-move-current-tab-to-right)
    ("b" ivy-switch-buffer)
    ("g" awesome-tab-counsel-switch-group)
    ("t" awesome-tab-ace-jump :exit t)
    ("C-k" kill-current-buffer)
    ("C-S-k" awesome-tab-kill-other-buffers-in-current-group)
    ("q" nil "quit"))
  ;; hide tabs
  (defun p1uxtar-awesome-tab-hide-tab (x)
    (let ((name (format "%s" x)))
      (or
       (string-prefix-p "*Ilist*" name)
       (string-prefix-p "*epc" name)
       (string-prefix-p "*helm" name)
       (string-prefix-p "*Compile-Log*" name)
       (string-prefix-p "*lsp" name)
       (and (string-prefix-p "magit" name)
            (not (file-name-extension name)))
       ;; customize hide tabs
       (string-prefix-p "flymake:" name)
       (string-prefix-p "*autoconnect-NOX " name)
       (string-prefix-p "*flycheck" name)
       (string-prefix-p "*NOX " name))))
  (setq awesome-tab-hide-tab-function 'p1uxtar-awesome-tab-hide-tab)
  ;; adjust tab height
  (setq awesome-tab-height 110))

;; -------- mode-line & awesome-tray --------

;; -------- doom-modeline -------- by seagle0128
(use-package doom-modeline
  :custom
  (doom-modeline-minor-modes t)
  (doom-modeline-unicode-fallback t)
  (doom-modeline-mu4e nil)
  :hook (after-init . doom-modeline-mode)
  :init
  ;; Prevent flash of unstyled modeline at startup
  (unless after-init-time
    (setq doom-modeline--default-format mode-line-format)
    (setq-default mode-line-format nil))
  :config
  ;; The limit of the window width, some information won't be displayed.
  (setq doom-modeline-window-width-limit fill-column)
  ;; How to detect the project root.
  (setq doom-modeline-project-detection 'project)
  ;; Whether display icons in the mode-line.
  (setq doom-modeline-icon (display-graphic-p))
  ;; a word count will be added to the selection-info modeline segment.
  (setq doom-modeline-enable-word-count t)
  ;; display the environment version.
  (setq doom-modeline-env-version t)
  ;; display while visiting a symbolink
  (setq find-file-visit-truename t)
  ;; reflect modeline when change branch
  (setq auto-revert-check-vc-info t)
  ;; specify (font family) in modeline
  ;; For example:
  ;; (setq doom-modeline-height 1)
  ;; (set-face-attribute 'mode-line nil :family "Noto Sans" :height 100)
  ;; (set-face-attribute 'mode-line-inactive nil :family "Noto Sans" :height 100)
  ;; or
  ;; (custom-set-faces
  ;;  '(mode-line ((t (:family "Noto Sans" :height 0.9))))
  ;;  '(mode-line-inactive ((t (:family "Noto Sans" :height 0.9)))))
  ;; display cursor positon & size indication.
  (setq column-number-mode t
        line-number-mode t
        size-indication-mode t))

;; -------- mini-modeline with smart-mode-line config --------
(use-package smart-mode-line
  :ensure t
  :config
  (setq sml/no-confirm-load-theme t)
  (sml/setup))
(use-package mini-modeline
  :ensure t
  :after smart-mode-line
  :config
  (mini-modeline-mode t))

;; -------- awesome-tray --------
(use-package awesome-tray
  :if window-system
  :load-path "lazycat-bucket/awesome-tray"
  ;; :init
  ;; (setq-default mode-line-format
  ;; 		(remove 'mode-line-buffer-identification mode-line-format))
  :hook
  ((after-init) . awesome-tray-mode)
  :config
  (custom-set-variables
   '(awesome-tray-active-modules '("location" "parent-dir" "git" "mode-name" "date"))))

;; -------- map different functions, distinguish according to `region-active-p' --------
;; emacs-china.org/t/region-active-transient-map/6932/7
(defconst angel-transient-mode-map-alist
  `((mark-active
     ,@(let ((map (make-sparse-keymap)))
         (define-key map "j" #'next-line)
         (define-key map "k" #'previous-line)
         (define-key map "h" 'backward-char)
         (define-key map "l" 'forward-char)
         (define-key map "d" 'p1uxtar-backward-kill-word-or-region)
         (define-key map "o" 'ace-window)
         (define-key map "q" #'keyboard-quit)
         ;; operations
         (define-key map "p" (lambda (b e)
                               (interactive "r") (delete-region b e) (yank)))
         (define-key map "x" #'exchange-point-and-mark)
         (define-key map ";" #'comment-dwim)
         (define-key map "y" #'kill-ring-save)
         (define-key map (kbd "C-y") #'counsel-yank-pop)
         (define-key map "Y" (lambda
                               (b e)
                               (interactive "r")
                               (kill-new (buffer-substring b e))
                               (message "Region saved")))
         ;; mark things
         (define-key map "f" #'er/mark-defun)
         (define-key map "w" #'er/mark-word)
         (define-key map "s" #'er/mark-symbol)
         (define-key map "M-h" #'er/mark-paragraph)
         ;; inner & outer
         ;; (define-key map "C-i" inner-map)
         ;; (define-key map "C-a" outer-map)
         ;; (define-key inner-map "q" #'er/mark-inside-quotes)
         ;; (define-key outer-map "q" #'er/mark-outside-quotes)
         ;; (define-key inner-map "b" #'er/mark-inside-pairs)
         ;; (define-key outer-map "b" #'er/mark-outside-pairs)
         ;; (define-key map "\"" #'er/mark-inside-quotes)
         (define-key map "\"" #'er/mark-outside-quotes)
         (define-key map "(" #'er/mark-inside-pairs)
         (define-key map ")" #'er/mark-outside-pairs)
         ;; expand-region
         ;; (define-key map (kbd "C--") #'er/contract-region)
         ;; (define-key map (kbd "C-=") #'er/expand-region)
         map))))
(add-to-list 'emulation-mode-map-alists
             'angel-transient-mode-map-alist t)

;; -------- powerline --------
(use-package powerline
  :ensure t
  :config
  (powerline-default-theme))

;; display window numbers on mode-line
(use-package winum
  :ensure t
  :config
  (setq winum-keymap
        (let ((map (make-sparse-keymap)))
          (define-key map (kbd "C-`") 'winum-select-window-by-number)
          (define-key map (kbd "M-0") 'winum-select-window-0-or-10)
          (define-key map (kbd "M-1") 'winum-select-window-1)
          (define-key map (kbd "M-2") 'winum-select-window-2)
          (define-key map (kbd "M-3") 'winum-select-window-3)
          (define-key map (kbd "M-4") 'winum-select-window-4)
          (define-key map (kbd "M-5") 'winum-select-window-5)
          (define-key map (kbd "M-6") 'winum-select-window-6)
          (define-key map (kbd "M-7") 'winum-select-window-7)
          (define-key map (kbd "M-8") 'winum-select-window-8)
          map))
  (defun winum-assign-9-to-calculator-8-to-flycheck-errors ()
    (cond
     ((equal (buffer-name) "*Calculator*") 9)
     ((equal (buffer-name) "*Flycheck errors*") 8)))
  (defun winum-assign-0-to-neotree ()
    (when (string-match-p (buffer-name) ".*\\*NeoTree\\*.*") 10))
  (add-to-list 'winum-assign-functions #'winum-assign-9-to-calculator-8-to-flycheck-errors)
  (add-to-list 'winum-assign-functions #'winum-assign-0-to-neotree)
  (set-face-attribute 'winum-face nil :weight 'bold)
  (setq window-numbering-scope            'global
        winum-reverse-frame-list          nil
        winum-auto-assign-0-to-minibuffer t
        winum-assign-func                 'my-winum-assign-func
        winum-auto-setup-mode-line        t
        winum-format                      " %s "
        winum-mode-line-position          1
        winum-ignored-buffers             '(" *which-key*")
        winum-ignored-buffers-regexp      '(" \\*Treemacs-.*"))
  (winum-mode))


;; -------- switch themes based on sunrise/sunset time. --------
(defvar dark-theme "Hesperus")
(defvar light-theme "Phosphorus")
;; get sunrise and sunset times
(defun get-time-of-solar ()
  "Switch themes based on the local times of sunrise and sunset."
  (let* ((sslist (split-string (sunrise-sunset) "[:apm\s]")))
    (setq sunrise-time (string-to-number
			            (concat (nth 1 sslist) (nth 2 sslist))))
    (setq sunset-time (string-to-number
		               (concat (nth 7 sslist) (nth 8 sslist))))))
;; set default time without location
(if (or (null calendar-latitude)
	    (null calendar-longitude))
    (progn
      (setq sunrise-time 600)
      (setq sunset-time 1800))
  (get-time-of-solar))
;; compare with current time to confirm theme
(if (> (string-to-number (format-time-string "%H")) 12)
    (if (> (string-to-number (format-time-string "%I%M"))
	       sunset-time)
	    (setq my-current-theme light-theme)
      (setq my-current-theme dark-theme))
  (if (> (string-to-number (format-time-string "%H%M"))
	     sunrise-time)
      (setq my-current-theme dark-theme)
    (setq my-current-theme light-theme)))
;; function to switch between two themes
(defun p1uxtar-Switch-themes ()
  "Switch themes between Hesperus & Phosphorus."
  (interactive)
  (cond
   ((string-equal my-current-theme "Hesperus")
    (progn
      (disable-theme 'Hesperus)
      (load-theme 'Phosphorus t)
      (setq my-current-theme "Phosphorus")))
   ((string-equal my-current-theme "Phosphorus")
    (progn
      (disable-theme 'Phosphorus)
      (load-theme 'Hesperus t)
      (setq my-current-theme "Hesperus"))))
  (when (display-graphic-p)
    (awesome-tray-mode 1))
  (when (eq system-type 'windows-nt)
    (p1uxtar-Win-frame-size)))
;; set position
(setq calendar-latitude 34.49
	  calendar-longitude 113.32)
(global-set-key (kbd "C-c S") #'p1uxtar-Switch-themes)


(use-package circadian
  :ensure t
  :config
  (setq calendar-latitude 34.7
 	    calendar-longitude 114.0)
  (setq circadian-themes '((:sunrise . Phosphorus)
                           (:sunset  . Hesperus)))
  (when (display-graphic-p)
    (awesome-tray-mode 1))
  (when (eq system-type 'windows-nt)
    (p1uxtar-Win-frame-size))
  (circadian-setup))

;; -------- set fonts better --------
;; blog.csdn.net/xh_acmagic/article/details/78939246
(defun p1uxtar-better-font ()
  (interactive)
  (if (display-graphic-p)
      (progn
        ;; english font
        (set-face-attribute 'default nil :font (format "%s:pixelsize=%d" "SF Mono" 14)) ;; 11 13 17 19 23
        ;; chinese font, same to chinese-fonts-setup, cnfonts
        (dolist (charset '(han kana symbol cjk-misc bopomofo))
          (set-fontset-font (frame-parameter nil 'font)
                            charset
                            (font-spec :family "Source Han Sans CN" :size 14)))) ;; 14 16 20 22 28
    ))
(defun p1uxtar-init-font (frame)
  (with-selected-frame frame
    (if (display-graphic-p)
        (p1uxtar-better-font))))
(if (and (fboundp 'daemonp) (daemonp))
    (add-hook 'after-make-frame-functions #'p1uxtar-init-font)
  (p1uxtar-better-font))

(use-package cnfonts
  :ensure t)

;; -------- expand <tab> with company yas --------
;; via: emacs.stackexchange.com/a/7925/12854
;; emacs.stackexchange.com/questions/7908/how-to-make-yasnippet-and-company-work-nicer
(defun check-expansion ()
  (save-excursion
    (if (looking-at "\\_>") t
      (backward-char 1)
      (if (looking-at "\\.") t
        (backward-char 1)
        (if (looking-at "->") t nil)))))

(defun do-yas-expand ()
  (let ((yas/fallback-behavior 'return-nil))
    (yas/expand)))

(defun tab-indent-or-complete ()
  (interactive)
  (cond
   ((minibufferp)
    (minibuffer-complete))
   (t
    (indent-for-tab-command)
    (if (or (not yas/minor-mode)
            (null (do-yas-expand)))
        (if (check-expansion)
            (progn
              (company-manual-begin)
              (if (null company-candidates)
                  (progn
                    (company-abort)
                    (indent-for-tab-command)))))))))

(defun tab-complete-or-next-field ()
  (interactive)
  (if (or (not yas/minor-mode)
          (null (do-yas-expand)))
      (if company-candidates
          (company-complete-selection)
        (if (check-expansion)
            (progn
              (company-manual-begin)
              (if (null company-candidates)
                  (progn
                    (company-abort)
                    (yas-next-field))))
          (yas-next-field)))))

(defun expand-snippet-or-complete-selection ()
  (interactive)
  (if (or (not yas/minor-mode)
          (null (do-yas-expand))
          (company-abort))
      (company-complete-selection)))

(defun abort-company-or-yas ()
  (interactive)
  (if (null company-candidates)
      (yas-abort-snippet)
    (company-abort)))

(global-set-key [tab] 'tab-indent-or-complete)
(global-set-key (kbd "TAB") 'tab-indent-or-complete)
(global-set-key [(control return)] 'company-complete-common)

(define-key company-active-map [tab] 'expand-snippet-or-complete-selection)
(define-key company-active-map (kbd "TAB") 'expand-snippet-or-complete-selection)

(define-key yas-minor-mode-map [tab] nil)
(define-key yas-minor-mode-map (kbd "TAB") nil)

(define-key yas-keymap [tab] 'tab-complete-or-next-field)
(define-key yas-keymap (kbd "TAB") 'tab-complete-or-next-field)
(define-key yas-keymap [(control tab)] 'yas-next-field)
(define-key yas-keymap (kbd "C-g") 'abort-company-or-yas)

;; -------- SAS custom function --------
(defun p1uxtar-SAS-vvalue ()
  "Get the formatted value that the variable under cursor."
  (interactive)
  (let ((symbol (thing-at-point 'symbol)))
    (when symbol (kill-new symbol)))
  (let ((beg (progn (skip-syntax-backward "^ " (line-beginning-position))
                    (point)))
        (end (progn (skip-syntax-forward "^ " (line-end-position))
                    (point))))
    (awesome-pair-wrap-round)
    (goto-char beg)
    (ess-yank)
    (insert "_v=vvalue")
    ;; (goto-char (+ end (- end beg)))
    (search-forward ")")
    (insert ";")
    (newline-and-indent)))

(provide '+backup)
